pub mod page_t {

use yew::prelude::*;
use yew::virtual_dom::VChild;
use yew::html_nested;
pub struct PageSidebar;

// Comp Component
impl Component for PageSidebar {
    type Message = ();

    type Properties = ();

    fn create(_ctx: &Context<Self>) -> Self {
        Self
    }

    fn view(&self, _ctx: &Context<Self>) -> Html {
        html!{
            <li>{"sidebar"}</li>
        }
    }
}

// Page Component Prop
#[derive(Properties, PartialEq)]
pub struct PageProps {
    #[prop_or_default]
    // virtual children Component , option for none available
    pub sidebar: Option<VChild<PageSidebar>>,
}

pub struct Page;

// Page Component
impl Component for Page {
    type Message = ();

    // Props is PageProps
    type Properties = PageProps;
        
    fn create(_ctx: &Context<Self>) -> Self {
        Self
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        html!{
            <div class="page">
            // take from scope take the props Option<VChild<T>>
            // Some for show None for default(nothing)
                { ctx.props().sidebar.clone().map(Html::from).unwrap_or_default() }
            </div>
        }
    }
}

// choice for render show
#[allow(dead_code)]
pub fn render_page(with_sidebar: bool) -> Html {
    if with_sidebar {
        html! {
            <Page sidebar={
                { 
                    html_nested!{
                        <PageSidebar />
                    }
                }
            } />
        }
    } else {
        html! {
            <div>
                <Page/>
                <p>{"nothing"}</p>
            </div>
        }
    }
}
}

// generic render Component
pub mod pg_t {

use yew::prelude::*;
use yew::virtual_dom::VChild;
// To allow the not really type
use std::marker::PhantomData;

#[derive(Clone, PartialEq, Properties)]
pub struct PageSidebar;

#[derive(Clone, PartialEq, Properties)]
pub struct PageSidebar2;

/// Component 1
impl Component for PageSidebar {
    type Message = ();

    type Properties = ();

    fn create(_ctx: &Context<Self>) -> Self {
        Self
    }

    fn view(&self, _ctx: &Context<Self>) -> Html {
        html!{
            <p>{"PageSidebar"}</p>
        }
    }
}

/// Component 2
impl Component for PageSidebar2 {
    type Message = ();

    type Properties = ();

    fn create(_ctx: &Context<Self>) -> Self {
        Self
    }

    fn view(&self, _ctx: &Context<Self>) -> Html {
        html!{
            <p>{"PageSidebar2"}</p>
        }
    }
}


// Option for Component

/// Option for Component as a prop
/// has generic available
#[derive(Clone, PartialEq, Properties)]
pub struct PageChildProp<T> 
where
// Only allow Component which impl the  trait <Component> sizeable <PartialEq>
    T: Component<Message = (), Properties = ()> + Sized + PartialEq,
{
    // store a virtual child
    pub obj: Option<VChild<T>>,
    // choice for render
    pub rd_alt: bool,
}
    
// add new function
impl<T> PageChildProp<T> 
where
    T: Component<Message = (), Properties = ()> + Sized + PartialEq,
{
    fn new(rd_alt: bool, obj: Option<VChild<T>>) -> Self {
        Self { rd_alt, obj }
    }
}

/// Page child which used to include Component
pub struct PageChild<T> 
where 
    T: Component<Message = (), Properties = ()> + Sized + PartialEq,
{
    pub props: PageChildProp<T>,
}

// as a middleware to choice for render show
impl<T> PageChild<T> 
where
    T: Component<Message = (), Properties = ()> + Sized + PartialEq,
{
    fn render_alt(&self) -> Html {
        if self.props.rd_alt {
            html! {
                <div>
                    {self.props.obj.clone().map(Html::from).unwrap_or_default()}
                </div>
            }
        } else {
            html! {
                <div>
                    {"nothing"}
                </div>
            }
        }
    }
}

impl<T> Component for PageChild<T> 
where
    T: Component<Message = (), Properties = ()> + Sized + PartialEq,
{
    type Message = ();

    type Properties = PageChildProp<T>;

    fn create(ctx: &Context<Self>) -> Self {
        let props = ctx.props();
        Self { 
            props: PageChildProp::new(props.rd_alt, props.obj.clone()),
        }
    }
    fn view(&self, _ctx: &Context<Self>) -> Html {
        html!{
            self.render_alt()
        }
    }
}


/// Page container only receive PageChild type object
#[derive(PartialEq, Properties)]
pub struct PageProps<T>
where 
    T: Component<Message = (), Properties = ()> + Sized + PartialEq,
{
    #[prop_or_default]
    pub children: ChildrenWithProps<PageChild<T>>,
}

// phantom_data cos of not used :T
pub struct Page<T>
where 
    T: Component<Message = (), Properties = ()> + Sized + PartialEq,
{
    phantom_data: PhantomData<T>,
}

impl<T> Component for Page<T>
where 
    T: Component<Message = (), Properties = ()> + Sized + PartialEq,
{
    type Message = ();

    type Properties = PageProps<T>;

    fn create(_ctx: &Context<Self>) -> Self {
        Self { phantom_data: PhantomData::<T>::default(), }
    }
    fn view(&self, ctx: &Context<Self>) -> Html {
        html!{
            <div class="page">
                {for ctx.props().children.iter()}
            </div>
        }
    }
}
}